'   fTray Project info class
'   Copyright (c) 2010 Marvin Westmaas ( MtM / Marvin_The_Martian )
'
'   This program is free software: you can redistribute it and/or modify
'   it under the terms of the GNU General Public License as published by
'   the Free Software Foundation, either version 3 of the License, or
'   (at your option) any later version.
'
'   This program is distributed in the hope that it will be useful,
'   but WITHOUT ANY WARRANTY; without even the implied warranty of
'   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'   GNU General Public License for more details.
'
'   You should have received a copy of the GNU General Public License
'   along with this program.  If not, see <http://www.gnu.org/licenses/>.
Imports System.Xml
Imports System.Xml.XPath
Imports System.Web
Imports System.Net

Public Class clsProjectInfo
    'GetIsDone to be used to notify completion
    Public Event GetIsDone()
#Region "Entry point"
    Public Sub New(ByVal DataLocation As String)
        DataLocation = DataLocation.TrimEnd("\")
        fileXML = DataLocation & "\Projects.xml"
        If My.Computer.FileSystem.FileExists(fileXML) Then ReadXML()
    End Sub
#End Region
#Region "Declares"
    Private urlPsummary As String = "http://fah-web.stanford.edu/psummaryC.html"
    Private fileXML As String = ""
    'Parsing constants
    Private Const parseHeader As String = "<th>Code</th><th>Description</th><th>Contact</th><th>Kfactor</th>"
    Private Const parseEnd As String = "</TABLE>"
    Private colProjects As New Collection
#End Region
#Region "Project info"
    'Structure declare
    Public Structure sProject
        Public ProjectNumber As String, ServerIP As String, WUName As String, NumberOfAtoms As String, PreferredDays As String, FinalDeadline As String
        Public Credit As String, Frames As String, Code As String, Description As String, Contact As String, kFactor As String
    End Structure
    Public ReadOnly Property IsEmpty() As Boolean
        Get
            If colProjects.Count = 0 Then
                Return True
            Else
                Return False
            End If
        End Get
    End Property
    'Used to enumerate collection
    Public ReadOnly Property ProjectNumber(ByVal Ind As Int16) As String
        Get
            Try
                If Ind > colProjects.Count Then Return vbNullString
                Dim rP As sProject = colProjects(Ind)
                Return rP.ProjectNumber
            Catch ex As Exception
                Return vbNullString
            End Try
        End Get
    End Property
    Public ReadOnly Property KnownProject(ByVal ProjectNumber As String) As Boolean
        Get
            Try
                Return colProjects.Contains(ProjectNumber)
            Catch ex As Exception
                Return False
            End Try
        End Get
    End Property
    Public ReadOnly Property ProjectCount() As Integer
        Get
            Return colProjects.Count
        End Get
    End Property
    Public ReadOnly Property Project(ByVal ProjectNumber) As sProject
        Get
            Try
                Return colProjects(ProjectNumber)
            Catch ex As Exception
                Return Nothing
            End Try
        End Get
    End Property
#End Region
#Region "Project download and parsing"
    Public Function GetProjects(Optional ByVal Url As String = "", Optional ByVal ShowUI As Boolean = False) As Boolean
        Try
            'check for network
            If Url = "" Then Url = urlPsummary
            If Not My.Computer.Network.IsAvailable Then Return False
            Dim allText As String = vbNullString
            Try
                Dim mC As WebClient = New WebClient
                allText = mC.DownloadString(Url)
            Catch ex As Exception
                Return False
            End Try
            If InStr(allText, "All Currently Running Projects") = 0 Then
                Return False
            Else
                allText = Mid(allText, InStr(allText, parseHeader) + Len(parseHeader))
            End If
            If Not ParseProjects(allText) Then
                colProjects.Clear()
                ReadXML()
                Return False
            End If
            WriteXML()
            RaiseEvent GetIsDone()
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function
    Private Function ParseProjects(ByVal allText As String) As Boolean
        Try
            Dim colKey As String ' every collection key is the projectnumber
            Dim strTmp As String ' needed because parsing in one time is sh1t
            Do
                'Cut to after <TD>
                Try
                    allText = Mid(allText, InStr(allText, "<td>") + 4)
                    colKey = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                    If Not colProjects.Contains(colKey) Then
                        Dim nProject As New sProject
                        With nProject
                            .ProjectNumber = colKey
                            'set blank
                            .WUName = "" : .ServerIP = "" : .PreferredDays = "" : .NumberOfAtoms = "" : .Frames = "" : .FinalDeadline = "" : .Code = "" : .Contact = "" : .Credit = "" : .Description = "" : .kFactor = ""
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .ServerIP = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .WUName = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .NumberOfAtoms = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .PreferredDays = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .FinalDeadline = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .Credit = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .Frames = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .Code = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            strTmp = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'Looks like "<a href=http://fah-web.stanford.edu/cgi-bin/fahproject?p=772>Description</a>"
                            If Mid(allText, 1, InStr(allText, "</td>") - 1).Trim <> "" Then .Description = Mid(strTmp, InStr(strTmp, "http"), InStr(strTmp, ">Des") - 9)
                            'Cut to after <td>
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            strTmp = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim
                            'looks like "<font size=-1>vvishal</font>"
                            strTmp = Mid(strTmp, InStr(strTmp, ">") + 1)
                            .Contact = Mid(strTmp, 1, Len(strTmp) - 7)
                            allText = Mid(allText, InStr(allText, "<td>") + 4)
                            'looks like asson</font></td><td>26.40</td></tr>
                            .kFactor = Mid(allText, 1, InStr(allText, "</td>") - 1).Trim

                        End With
                        colProjects.Add(nProject, colKey)
                    Else
                        'cut alltext
                        For tentimes As Int16 = 1 To 10
                            allText = Mid(allText, InStr(allText, "<TD>") + 4)
                        Next
                    End If
                Catch ex As Exception
                    Console.WriteLine(ex.Message)
                    'hehe no doubles :D
                End Try
                If InStr(allText, "<td>") = 0 Then Exit Do
            Loop
            Return True
        Catch ex As Exception
            Debug.Print(ex.Message)
            Return False
        End Try
    End Function
#End Region
#Region "XML writing/reading"
    Private Sub WriteXML()
        If My.Computer.FileSystem.FileExists(fileXML) Then My.Computer.FileSystem.DeleteFile(fileXML)
        Dim xSettings As New XmlWriterSettings
        xSettings.Indent = True
        xSettings.IndentChars = "    "
        Dim xWriter As XmlWriter = XmlWriter.Create(fileXML, xSettings)
        xWriter.WriteStartElement("Projects")
        xWriter.WriteStartElement("Count")
        xWriter.WriteString(colProjects.Count.ToString)
        xWriter.WriteEndElement()
        For Each nProject As sProject In colProjects
            With xWriter
                .WriteStartElement("Project")
                .WriteStartElement("Projectnumber")
                .WriteString(nProject.ProjectNumber)
                .WriteEndElement()
                .WriteStartElement("ServerIP")
                .WriteString(nProject.ServerIP)
                .WriteEndElement()
                .WriteStartElement("WorkunitName")
                .WriteString(nProject.WUName)
                .WriteEndElement()
                .WriteStartElement("NumberOfAtoms")
                .WriteString(nProject.NumberOfAtoms)
                .WriteEndElement()
                .WriteStartElement("PreferredDays")
                .WriteString(nProject.PreferredDays)
                .WriteEndElement()
                .WriteStartElement("FinalDeadline")
                .WriteString(nProject.FinalDeadline)
                .WriteEndElement()
                .WriteStartElement("Credit")
                .WriteString(nProject.Credit)
                .WriteEndElement()
                .WriteStartElement("Frames")
                .WriteString(nProject.Frames)
                .WriteEndElement()
                .WriteStartElement("Code")
                .WriteString(nProject.Code)
                .WriteEndElement()
                .WriteStartElement("Description")
                .WriteString(nProject.Description)
                .WriteEndElement()
                .WriteStartElement("Contact")
                .WriteString(nProject.Contact)
                .WriteEndElement()
                .WriteStartElement("kFactor")
                .WriteString(nProject.kFactor)
                .WriteEndElement()
                .WriteEndElement()
            End With
        Next
        xWriter.WriteEndElement()
        xWriter.Close()
    End Sub
    Public Function ReadXML() As Boolean
        Try
            Dim Xreader As XmlReader = XmlReader.Create(fileXML)
            Dim intCount As Int16
            'Clean collections
            Xreader.ReadStartElement("Projects")
            Xreader.ReadStartElement("Count")
            intCount = CInt(Xreader.ReadString)
            Xreader.ReadEndElement()
            For Counter As Int16 = 1 To intCount
                Dim nProject As New sProject
                With Xreader
                    .ReadStartElement("Project")
                    .ReadStartElement("Projectnumber")
                    nProject.ProjectNumber = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("ServerIP")
                    nProject.ServerIP = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("WorkunitName")
                    nProject.WUName = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("NumberOfAtoms")
                    nProject.NumberOfAtoms = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("PreferredDays")
                    nProject.PreferredDays = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("FinalDeadline")
                    nProject.FinalDeadline = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("Credit")
                    nProject.Credit = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("Frames")
                    nProject.Frames = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("Code")
                    nProject.Code = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("Description")
                    nProject.Description = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("Contact")
                    nProject.Contact = .ReadString
                    .ReadEndElement()
                    .ReadStartElement("kFactor")
                    nProject.kFactor = .ReadString
                    .ReadEndElement()
                    .ReadEndElement()
                    colProjects.Add(nProject, nProject.ProjectNumber)
                End With
            Next
            Xreader.Close()
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function

#End Region
    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub
End Class
